<template>
    <ph-flex class="ph-table-layout" ref="etable">
        <table-action-bar 
            :ths="ths"
            :action="tableAction"
            v-if="tableAction"
            @col-filter="onColFilter"
            @export="onExport"
            @print="onPrint"
            @del-checked="onDelChecked"/>
        <ph-flex class="ph-table-container">
            <ph-table v-if="lths.length"
            :ths="lths" 
            :sum="openSum"
            :list="records" lock="left" 
            :sortName="sortName" 
            :sortMode="sortMode" 
            :checkedRecord="checked"/>
            <ph-flex class="ph-table-scroll">
                <ph-table
                :ths="nths" 
                :sum="openSum"
                :list="records" 
                :sortName="sortName" 
                :sortMode="sortMode" 
                :checkedRecord="checked"/>
            </ph-flex>
            <ph-table v-if="rths.length"
            :ths="rths" 
            :sum="openSum"
            :list="records" lock="right" 
            :sortName="sortName" 
            :sortMode="sortMode" 
            :checkedRecord="checked"/>
        </ph-flex>
        <pager class="ph-table-pager" v-if="pager" 
        :prev="prev"
        :next="next"
        :total="total" 
        :page="page" 
        :theme="pagerType"
        :show-total="showTotal"
        :show-pagesize="showPagesize"
        :show-jump="showJump"
        :pagesize-options="pagesizeOptions"
        :justify="pageJustify"
        @page="onPage"
        />
        <loading class="ph-table-loading" ref="loading"/>
    </ph-flex>
</template>
<script lang="ts">
import { computed, defineAsyncComponent, defineComponent, onMounted, onUnmounted, PropType, provide, ref, unref } from 'vue'
import { export2xls , export2csv } from 'ph-export'
import {PhFlex} from '../base'
import {ITh,SortStatus,RowAction,TableAction} from './struct'
import PhTable from './table.vue'
import TableActionBar from './table-action.vue'
import Loading from '../loading/main.vue'
import {PhLoadingState} from '../loading/index.type'
export default defineComponent({
    components:{
        PhFlex,
        Loading,
        PhTable,
        //异步加载组装页面会抖动
        TableActionBar,//:defineAsyncComponent(()=>import('./table-action.vue'))
        Pager:defineAsyncComponent(()=>import('../pager/pager.vue')),
    },
    props:{
        rowAction:{
            type:Object as PropType<RowAction>
        },
        tableAction:{
            type:Object as PropType<TableAction>
        },
        name:{
            type:String //表格的title，用于导出时的名字
        },
        check:{
            type:Boolean
        },
        radio:{
            type:Boolean
        },
        ths:{
            type: Array as PropType<Array<ITh>>,
            default:()=>[]
        },
        list:{
            type: Array as PropType<Array<Record<string,unknown>>>,
            default:()=>[]
        },
        checked:{
            type: Array as PropType<Array<string|number>>
        },
        pager:{
            type:Boolean //是否启用分页
        },
        pageJustify:{
            type:String,
            default:"flex-end"
        },
        pagerType:{type:String,default:'transparent'},

        //分页配置
        total:{type:Number,default:0}, //参考分页
        page:{type:Number,default:1} , //参考分页
        prev:{type:String},
        next:{type:String},
        "show-total":{type:Boolean,default:true},
        "show-pagesize":{type:Boolean,default:true},
        "show-jump":{type:Boolean,default:true},
        "pagesize-options":{
            type:Array
        }
    },
    setup(props,{emit,expose}){
        const etable = ref<InstanceType<typeof PhFlex>>()
        const loading = ref<InstanceType<typeof Loading>>()
        const sortName = ref<string>("")
        const sortMode = ref<SortStatus>(SortStatus.none)
        const sortDataType = ref("")
        const cacheCheckeds = ref<Array<string|number>>(props.checked||[])
        const filterThs = ref<Array<ITh>>(props.ths)
        const sortFn = (a:Record<string,unknown>,b:Record<string,unknown>)=>{
            switch(sortDataType.value){
                case 'number':{
                    const v1 = Number(a[sortName.value])
                    const v2 = Number(b[sortName.value])
                    return sortMode.value===SortStatus.asc?v1-v2:v2-v1;
                }
                case 'date':{
                    try{
                        const v1 = new Date(a[sortName.value] as string).getTime()
                        const v2 = new Date(b[sortName.value] as string).getTime()
                        return sortMode.value===SortStatus.asc?v1-v2:v2-v1;
                    }catch(e){
                        console.warn(e)
                        return 0
                    }
                }
                default:{
                    const v1 = String(a[sortName.value]).toLowerCase()
                    const v2 = String(b[sortName.value]).toLowerCase()
                    const flag = v1<v2?-1:1
                    return sortMode.value===SortStatus.asc?flag:-flag;
                } 
            }
        }
        const records = computed(()=>{
            if(sortName.value&&sortMode.value!==SortStatus.none){
                return (JSON.parse(JSON.stringify(props.list)) as Record<string,unknown>[]).sort(sortFn)//.sort(sortFn)
            }
            return props.list
        })
        const lths = computed(()=>{
            const lths = filterThs.value.filter(obj=>obj.lock&&obj.lockPos=="left")
            if(!lths.length)return []
            if(props.check)return [{check:'check'},...lths]
            if(props.radio)return [{check:'radio'},...lths]
            return lths
        })
        const rths = computed(()=>{
            const rths = filterThs.value.filter(obj=>obj.lock&&obj.lockPos=="right")
            if(props.rowAction){
                return [...rths,{
                    rowAction:props.rowAction
                }]
            }
            return rths
        })

        const nths = computed(()=>{
            const nths = filterThs.value.filter(obj=>!obj.lock)
            if(lths.value.length)return nths
            if(props.check)return [{check:'check'},...nths]
            if(props.radio)return [{check:'radio'},...nths]
            return nths
        })
        const openSum = computed(()=>{
            return filterThs.value.some(th=>th.sum===true)
        })
        
        const onCheckAll = (v:boolean)=>{
            console.log(v,'checkall')
            if(v)
                cacheCheckeds.value = props.list.map(item=>item.id as string)
            else cacheCheckeds.value = []
            notifyCheck([...unref(cacheCheckeds)])
        }
        const onCheck = (id:string|number,checked:boolean)=>{
            if(props.check){
                if(checked)cacheCheckeds.value.push(id)
                else cacheCheckeds.value = cacheCheckeds.value.filter(id1=>id!=id1)
                notifyCheck([...unref(cacheCheckeds)])
            }else if(props.radio){
                if(checked) cacheCheckeds.value = [id]
                else cacheCheckeds.value = []
                notifyCheck([...unref(cacheCheckeds)])
            }
        }
        const onSort = (v:number,key:string,dt:string)=>{
            console.log(v)
            sortMode.value = v
            sortName.value = key
            sortDataType.value = dt
        }
        const notifyCheck = (arr:Array<string|number>)=>{
            emit('check',arr)
        }
        const onPage = (data:{page:number})=>{
            emit("page",data)
        }
        const onTdClick = (key:string,row:Record<string,unknown>)=>{
            emit('td-click',key,row)
        }
        const onTrClick = (id:string|number,row:Record<string,unknown>)=>{
            emit('tr-click',id,row)
        }
        const onRowView = (row:Record<string,unknown>)=>{
            emit('row-view',row)
        }
        const onRowEdit = (row:Record<string,unknown>)=>{
            emit('row-edit',row)
        }
        const onRowDel = (row:Record<string,unknown>)=>{
            emit('row-del',row)
        }
        const onDelChecked = ()=>{
            if(!cacheCheckeds.value.length)return
            emit('del-checked',cacheCheckeds.value)
        }
        const onExport = (type:string)=>{
            let str = filterThs.value.map(th=>th.name).join(",")+"\n"//表头
            str+=props.list.map(row=>{
                return filterThs.value.map(th=>row[th.key]||'').join("\t,")
            }).join("\n")
            if(type=="xls")
            export2xls(str,props.name)
            if(type=="csv")
            export2csv(str,props.name)
        }
        const onColFilter = (v:Array<string>)=>{
            filterThs.value = props.ths.filter(th=>v.includes(th.key))
        }
        const onPrint = ()=>{
            const tb = etable.value?.$el;
            {
                if(tb){
                    const tb1 = tb?.cloneNode(true) as HTMLElement
                    tb1.id="ph-tmp"
                    tb1.querySelector(".ph-table-container")?.classList.add("ph-print")
                    document.body.appendChild(tb1)
                }
            }
            setTimeout(()=>{
                window.print()
            })
        }
        const cancelFullScreen = ()=>{
            const printDom = document.querySelector("#ph-tmp")
            printDom&&document.body.removeChild(printDom)
        }
		onMounted(()=>{
			window.addEventListener("afterprint",cancelFullScreen)
		})
		onUnmounted(()=>{
			window.removeEventListener("afterprint",cancelFullScreen)
		})
        provide('tbRowView',onRowView)
        provide('tbRowEdit',onRowEdit)
        provide('tbRowDel',onRowDel)
        provide('toggleTbCheckAll',onCheckAll)
        provide('toggleTbCheck',onCheck)
        provide('tbSort',onSort)
        provide('tdClick',onTdClick)
        provide('trClick',onTrClick)

        const showLoading=(opt?:PhLoadingState)=>{
            loading.value?.show(opt)
        }
        const hideLoading=()=>loading.value?.hide()
        return {
            etable,
            loading,
            showLoading,
            hideLoading,
            lths,
            rths,
            nths,
            openSum,
            records,
            sortName,
            sortMode,
            onExport,
            onColFilter,
            onDelChecked,
            onPrint,
            onPage}
    }
})
</script>
<style lang="scss">
.ph-table-layout{
    flex-direction: column;
    margin: var(--ph-15) 0;
    overflow: visible;
    width: 100%;
    min-width: 100%;
    .ph-table-loading{
        position:absolute;
        background-color:rgba(255,255,255,.3);
        color:var(--ph-c);
    }
    .ph-table-pager{
        border:1px solid var(--ph-bd-light);
        border-top: none;
        padding: var(--ph-8) var(--ph-15);
    }
    .ph-table-container{
        background-color: #FFF;
        color:var(--ph-c);
        overflow: hidden;
        position: relative;
        min-width: 100%;
        &.ph-print{
            position: fixed;
            top: 0;
            left: 0;
            z-index: 999999;
            bottom: 0;
        }
        &:before,
        &:after{
            content:"";
            position: absolute;
            background-color: var(--ph-bd-light);
        }
        &:before{
            bottom: 0;
            left:0;
            right:0;
            height: 1px;
            z-index: 1;
        }
        &:after{
            top:0;
            bottom: 0;
            right:0;
            width: 1px;
            background-color: var(--ph-bd-light);
            z-index: 1;
        }
        .ph-table-scroll{
            flex: 1;
            overflow-y: auto;
            .ph-table{
                flex: 1;
            }
        }
        .ph-table + .ph-table-scroll{
            margin-left: -1px;
        }
    }
}

</style>